package com.indiv.pmy.shape;

import java.awt.Color;
import java.awt.Graphics;

import com.indiv.pmy.transform.TransformFactory;
import com.indiv.pmy.vector.Vector2d;

public class Rectangle extends Shape {
	Point topLeft;
	Point[] vertices;
	double width;
	double height;
	
	double rotated;
	
	public Rectangle() {
		topLeft = new Point(0,0);
		width = 10.0;
		height = 10.0;
		vertices = new Point[4];
		vertices[0] = new Point(0,0);
		vertices[1] = new Point(width,0);
		vertices[2] = new Point(width,height);
		vertices[3] = new Point(0,height);
		rotated = 0;
	}
	
	public Rectangle(double _topLeftX, double _topLeftY, double _width, double _height) {
		topLeft = new Point(_topLeftX,_topLeftY);
		width = _width;
		height = _height;
		vertices = new Point[4];
		vertices[0] = new Point(topLeft.x,topLeft.y);
		vertices[1] = new Point(topLeft.x+width,topLeft.y);
		vertices[2] = new Point(topLeft.x+width,topLeft.y+height);
		vertices[3] = new Point(topLeft.x,topLeft.y+height);
		rotated = 0;
	}
	
	public Rectangle(double _topLeftX, double _topLeftY, double _width, double _height, double _angle) {
		topLeft = new Point(_topLeftX,_topLeftY);
		width = _width;
		height = _height;
		vertices = new Point[4];
		vertices[0] = new Point(topLeft.x,topLeft.y);
		vertices[1] = new Point(topLeft.x+width,topLeft.y);
		vertices[2] = new Point(topLeft.x+width,topLeft.y+height);
		vertices[3] = new Point(topLeft.x,topLeft.y+height);
		rotated = _angle;
		
		//we need to rotate it now...
		double[][] rotationMatrix = TransformFactory.generateRotationMatrix(rotated);
		rotate(rotationMatrix);
	}
	
	@Override
	public void draw(Graphics _g) {
		Color old = _g.getColor();
		_g.setColor(Color.black);
		int[] xPoints = {(int) Math.round(vertices[0].x), (int)Math.round(vertices[1].x), 
						 (int) Math.round(vertices[2].x), (int)Math.round(vertices[3].x)};
		int[] yPoints = {(int) Math.round(vertices[0].y), (int)Math.round(vertices[1].y), 
					     (int) Math.round(vertices[2].y), (int)Math.round(vertices[3].y)};
		_g.drawPolygon(xPoints, yPoints, 4);
		_g.setColor(old);
	}
	
	public void destroy() {
		vertices = null;
		rotated = 0;
		width = 0;
		height = 0;
	}

	@Override
	public void rotate(double[][] _rotationMatrix) {
		//First center the object around virtual origin so it's easier to rotate
		double _offsetX = topLeft.x+(width/2.0);
		double _offsetY = topLeft.y+(height/2.0);
		Point center = new Point(_offsetX, _offsetY);
		Vector2d[] tempVertices = {new Vector2d(vertices[0].x-center.x,vertices[0].y-center.y),
							    	new Vector2d(vertices[1].x-center.x,vertices[1].y-center.y),
							    	new Vector2d(vertices[2].x-center.x,vertices[2].y-center.y),
							    	new Vector2d(vertices[3].x-center.x,vertices[3].y-center.y)};
		
		//Normalize the vectors
		double[] norms = {tempVertices[0].norm(), tempVertices[1].norm(),
						  tempVertices[2].norm(),tempVertices[3].norm()};
		for(Vector2d v : tempVertices) {
			v.makeUnitVector();
		}
		
		//Now we can rotate it by multiplying by the rotation matrix
		for(Vector2d v : tempVertices) {
			v.setI((_rotationMatrix[0][0]*v.getI())+(_rotationMatrix[0][1]*v.getJ()));
			v.setJ((_rotationMatrix[1][0]*v.getI())+(_rotationMatrix[1][1]*v.getJ()));
		}
		
		for(Vector2d v : tempVertices) {
			v.makeUnitVector();
		}
		
		//Rescale it by the norm of each vector
		for(int i = 0; i < 4; i++) {
			tempVertices[i].scale(norms[i]);
		}
		
		//Reset the points
		for(int k = 0; k < 4; k++) {
			vertices[k].x = tempVertices[k].getI()+_offsetX;
			vertices[k].y = tempVertices[k].getJ()+_offsetY;
		}
	}

	@Override
	public void translate(double[] _translationMatrix) {
		for(Point p : vertices) {
			p.setX(p.x+_translationMatrix[0]);
			p.setY(p.y+_translationMatrix[1]);
		}
		topLeft.x += _translationMatrix[0];
		topLeft.y += _translationMatrix[1];
	}

	@Override
	public void scale(double[] _scaleMatrix) {
		//Compute the center point
		Point center = new Point(topLeft.x+width/2,topLeft.y+height/2);
		
		//For each vertex determine the vector from the center to the point and scale it.
		Vector2d[] vectors = {new Vector2d(vertices[0].x-center.x, vertices[0].y-center.y),
							  new Vector2d(vertices[1].x-center.x, vertices[1].y-center.y),
							  new Vector2d(vertices[2].x-center.x, vertices[2].y-center.y), 
							  new Vector2d(vertices[3].x-center.x, vertices[3].y-center.y)};
		for(Vector2d v : vectors) {
			v.scale(_scaleMatrix[0], _scaleMatrix[1]);
		}
		
		//Add the new vector to the center point vector to determine the new point
		for(int k = 0; k < 4; k++) {
			vertices[k] = new Point(center.x+vectors[k].getI(),center.y+vectors[k].getJ());
		}
		
		//Update the widths and heights...easy part
		width = width*_scaleMatrix[0];
		height = height*_scaleMatrix[1];
		
		//Almost done we can't forget to update the top left corner of this guy,
		//which will always have vector <center.x-width/2 center.y-height/2>
		topLeft = new Point(center.x-width/2, center.y-height/2);
	}

	@Override
	public double getX() {
		return topLeft.x;
	}

	@Override
	public double getY() {
		return topLeft.y;
	}
	
}
